package com.scienview.core.util;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;


public class ClassSearchUtil {
static String RESOURCE_PATTERN = "**/*.class";
	
	/** 获得某个包下的所有类,不包括内部类 */
	public static List<Class<?>> getClass(String packageName) {
	 List<Class<?>> classes=new ArrayList<Class<?>>();
	 ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
				+ ClassUtils.convertClassNameToResourcePath(packageName) + RESOURCE_PATTERN;
		try {
			Resource[] resource = resourcePatternResolver.getResources(pattern);
			for (Resource rs : resource) {
				String fileName=rs.getURL().getPath();
				if(fileName.indexOf('$')!=-1){
					continue;
				}
				//对于在jar包里的类,去掉jar!/以前的东西
				fileName=StringUtil.getLastAfter(fileName, "jar!/");
				//在classes里的去掉classes以前的东西
				fileName=StringUtil.getLastAfter(fileName, "classes/");
				fileName=fileName.replaceAll("/", ".");
				fileName=StringUtil.getLastBefore(fileName, ".class");
				
				classes.add(Class.forName(fileName));		
			}
			return classes;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static List<Class<?>> getAnnotationClass(String packageName,Class<? extends Annotation> annotation){
		 List<Class<?>> classes=new ArrayList<Class<?>>();
		 ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
			String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ ClassUtils.convertClassNameToResourcePath(packageName) + RESOURCE_PATTERN;
			System.out.println(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			try {
				Resource[] resources = resourcePatternResolver.getResources(pattern);
				for (Resource resource : resources) {
					if (resource.isReadable()) {
						MetadataReader reader = readerFactory.getMetadataReader(resource);
						Class<?> clazz=Class.forName(reader.getClassMetadata().getClassName());
						if(clazz.isAnnotationPresent(annotation)){
							classes.add(clazz);
						}
					}
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			return classes;
			
	}
	
	public static List<Class<?>> getImplementClass(String packageName,Class<?> interfaces){
		 List<Class<?>> classes=new ArrayList<Class<?>>();
		 ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
			String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ ClassUtils.convertClassNameToResourcePath(packageName) + RESOURCE_PATTERN;
			System.out.println(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			try {
				Resource[] resources = resourcePatternResolver.getResources(pattern);
				for (Resource resource : resources) {
					if (resource.isReadable()) {
						MetadataReader reader = readerFactory.getMetadataReader(resource);
						try{
								Class<?> clazz=Class.forName(reader.getClassMetadata().getClassName());
								//System.out.println(clazz);
								if(interfaces.isAssignableFrom(clazz)){
									classes.add(clazz);
								}
							
						}catch(Exception e){
							//e.printStackTrace();
						}
					}
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			return classes;
			
	}
	
	
	public static void main(String[]args){
	
		List<Class<?>>classes=getImplementClass("org.springframework.web.context.",ConfigurableWebApplicationContext.class);
		System.out.println(classes);
	}
}
